package com.ericsson.common.util;

import com.ericsson.common.pojo.CdrDownVo;
import com.ericsson.common.pojo.FTPInfoVO;
import org.apache.commons.net.ftp.*;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 文件下载的工具类
 *
 * @author root
 *
 */
public class FtpCarrierUtil {
	private org.slf4j.Logger log;
	private FTPInfoVO ftpConf;
	private FTPClient ftpClient = new FTPClient();

	public FtpCarrierUtil(FTPInfoVO ftpConf, org.slf4j.Logger log) {
		this.ftpConf = ftpConf;
		this.log = log;
	}


	/**
	 * Configuration
	 *
	 * @return
	 */
	private FTPClientConfig getConfigure() {
		FTPClientConfig configure = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
		configure.setServerLanguageCode("zh");
		return configure;
	}

	/**
	 * Open the FTP connection
	 *
	 */
	public void connect() throws Exception {
		int reply = 0;
		if (!ftpClient.isConnected()) {
			ftpClient = new FTPClient();
			ftpClient.connect(this.ftpConf.getHost(), this.ftpConf.getPort());
			ftpClient.setControlEncoding("ISO-8859-1");
			ftpClient.configure(getConfigure());
			ftpClient.setBufferSize(1024 * 1024 * 10);
			ftpClient.setConnectTimeout(2*60*1000);
			ftpClient.setSoTimeout(2*60*1000);
			ftpClient.setControlKeepAliveReplyTimeout(5000);
			ftpClient.setControlKeepAliveTimeout(5000);
			ftpClient.setDataTimeout(2*60*1000);
			ftpClient.login(this.ftpConf.getUserName(), this.ftpConf.getPassword());
			reply = ftpClient.getReplyCode();
			if (!this.ftpConf.isSsl()) {
				if (!FTPReply.isPositiveCompletion(reply)) {
					ftpClient.disconnect();
					return;
				}
			}
		}
	}

	/**
	 * Close the current connection
	 */
	public void close() throws IOException {
		if (ftpClient.isConnected()) {
			this.ftpClient.logout();
			this.ftpClient.disconnect();
		}
	}



	public CdrDownVo download_IMSCDR(String subDirs, String date, CdrDownVo cdrDownVoLast) {
		// 上一次 cdrDownVoLast

		log.info("downInit===:" + cdrDownVoLast.getFileName() + "|" + cdrDownVoLast.getTimeAndNum() + "date" + date);
		CdrDownVo cdrDownVoCurrent = new CdrDownVo();// 当前
		CdrDownVo cdrDownVoEnd = new CdrDownVo(); // 本次最后
		try {
			String path = this.ftpConf.getPath();

			log.info(path + " date " + date + " analysiPath(path, date) " + analysiImsPath(path, date));
			boolean changFlag = ftpClient.changeWorkingDirectory(analysiImsPath(path, date));
			int fileCount = 0;
			if (changFlag) {
				ftpClient.enterLocalPassiveMode();
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
				FTPFile[] ftpFiles = ftpClient.listFiles();
				log.info("===== ftpFiles num: " + ftpFiles.length + " date :" + date + " analysiPath(path, date): "
						+ analysiImsPath(path, date));
				List<FTPFile> ll = new ArrayList<FTPFile>();
				for (int m = 0; m < ftpFiles.length; m++) {
						ll.add(ftpFiles[m]);
				}
				for (int i = 0; i < ll.size(); i++) {

					// TimeAndNum为零表示第一次下载，只下载最新的5个文件
					if (cdrDownVoLast.getTimeAndNum() == 0 && ll.size() - i > 5) {
						continue;
					}
					FTPFile ftpFile = ll.get(i);

					if (!ftpFile.getName().equals(".") && !ftpFile.getName().equals("..") && !ftpFile.isDirectory()) {
						cdrDownVoCurrent.setFileName(ftpFile.getName());
						if (cdrDownVoLast.getTimeAndNum() < cdrDownVoCurrent.getTimeAndNum()) {

							fileCount++;
							String originalName="";
							if(ftpFile.getName().contains(".gz:")) {
								originalName=new String((ftpFile.getName()+".gz").getBytes("ISO-8859-1"), "UTF-8");
							}else{
								originalName=new String(ftpFile.getName().getBytes("ISO-8859-1"), "UTF-8");
							}
							File storeDir = FileUtil.newDirs(
									subDirs + File.separator + this.ftpConf.getNetElementID() + File.separator);
							File localFile = new File(storeDir, originalName);

							if (!localFile.exists()) {
								OutputStream outputStream = new FileOutputStream(localFile);
								ftpClient.retrieveFile(ftpFile.getName(), outputStream);
								outputStream.close();
								if(ftpFile.getName().contains(".gz:")){
									gzipFile(localFile);
								}
							}
							if (cdrDownVoEnd.getTimeAndNum() < cdrDownVoCurrent.getTimeAndNum()) {
								String[] subStr = ftpFile.getName().toUpperCase().split(":")[1].split("_");
								cdrDownVoEnd.setLoadFileModifyTime(
										(new SimpleDateFormat("yyyyMMddHHmmSS").parse(subStr[subStr.length - 2]))
												.getTime());
								cdrDownVoEnd.setFileName(ftpFile.getName());
							}
						}
					}
				}
			} else {
				log.info("FtpCarrierUtil>> changeWorkingDirectory failed " + analysiImsPath(path, date) + " is not found");
				return null;
			}

			// 此次下载未下载到新文件时，将上一次的标志赋值给本次
			if (cdrDownVoEnd.getLoadFileModifyTime() == 0) {
				cdrDownVoEnd.setLoadFileModifyTime(cdrDownVoLast.getLoadFileModifyTime());
				cdrDownVoEnd.setFileName(cdrDownVoLast.getFileName());
			}
			log.info("==cg_cdrpath " + path + "====file download count is[ :" + fileCount + "]  path: "
					+ analysiImsPath(path, date));
		} catch (Exception e) {
			log.info("FtpCarrierUtil>>file download exception：" + e.getMessage(), e);
			return null;
		}
		log.info(" ===== last downloadfile time  is" + cdrDownVoEnd.getLoadFileModifyTime() + " date :" + date);
		log.info("downEnd===:" + cdrDownVoEnd.getFileName() + "|" + cdrDownVoEnd.getTimeAndNum() + " dirpath :"
				+ " date :" + date);
		return cdrDownVoEnd;
	}

	public Set<String> download_VGCCDR(String fileNameType, String subDirs, String date, TreeSet<String> sortSet, boolean down) {
		Set<String> downFileResult=new TreeSet<>();
		try {
			String path = this.ftpConf.getPath();
			String storePath= analysisVgcStorePath(subDirs,path);
			File storeDir = FileUtil.newDirs(storePath);

			String analysisPathResult=analysiVgcPath(path, date);
			log.info("fileNameType:"+fileNameType+"：path"+path + " date " + date + " analysiPathResult " + analysisPathResult);
			boolean changFlag = ftpClient.changeWorkingDirectory(analysisPathResult);
			if (changFlag) {
				ftpClient.enterLocalPassiveMode();
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
				FTPFile[] ftpFiles = ftpClient.listFiles();
				log.info("fileNameType:"+fileNameType+"===== ftpFiles num: " + ftpFiles.length + " date :" + date + " analysiPathResult: "
						+analysisPathResult);
				List<FTPFile> ll = new ArrayList<FTPFile>();
				for (int m = 0; m < ftpFiles.length; m++) {
					if(ftpFiles[m].getName().contains(fileNameType)) {
						ll.add(ftpFiles[m]);
					}
				}
				for (int i = 0; i < ll.size(); i++) {
						FTPFile ftpFile = ll.get(i);
						if (!ftpFile.getName().equals(".") && !ftpFile.getName().equals("..") && !ftpFile.isDirectory()) {
							if (!sortSet.contains(ftpFile.getName())) {
								String originalName = "";
								if (ftpFile.getName().contains(".gz:")) {
									originalName = new String((ftpFile.getName() + ".gz").getBytes("ISO-8859-1"), "UTF-8");
								} else {
									originalName = new String(ftpFile.getName().getBytes("ISO-8859-1"), "UTF-8");
								}
								File localFile = new File(storeDir, originalName);
								if (!localFile.exists()&&down) {
									OutputStream outputStream = new FileOutputStream(localFile);
									ftpClient.retrieveFile(ftpFile.getName(), outputStream);
									log.info("fileNameType:"+fileNameType+"download file >>>>>>:" + ftpFile.getName());
									outputStream.close();
									if (ftpFile.getName().contains(".gz:")) {
										gzipFile(localFile);
									}
								}
								downFileResult.add(ftpFile.getName());
							}
					}
				}
			} else {
				log.info("fileNameType:"+fileNameType+"FtpCarrierUtil>> changeWorkingDirectory failed " + analysisPathResult + " is not found");
				return null;
			}
		} catch (Exception e) {
			log.info("fileNameType:"+fileNameType+"FtpCarrierUtil>>file download exception：" + e.getMessage(), e);
			return null;
		}
		return downFileResult;
	}

	private void gzipFile(File localFile) {
			Process procMv;
			String[] cmdMv = new String[3];
			cmdMv[0] = "sh";
			cmdMv[1] = "-c";
			cmdMv[2] = "/usr/bin/gzip -d "
					+localFile.getPath();
			try {
				procMv = Runtime.getRuntime().exec(cmdMv);
				BufferedReader brMv = new BufferedReader(new InputStreamReader(procMv.getInputStream()));
				String lineMv;
				while ((lineMv = brMv.readLine()) != null) {
					if (lineMv.trim().endsWith("#")) {
						break;
					}
				}
				brMv.close();
				procMv.waitFor();
				procMv.destroy();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
	}

	/**
	 *
	 * @param fileListDownloaded
	 */
	@SuppressWarnings("rawtypes")
	public void moveFile(List<File> fileListDownloaded, String cdrFileDoneDir) {
		for (Iterator iterator = fileListDownloaded.iterator(); iterator.hasNext();) {
			File file = (File) iterator.next();
			FileUtil.syncMoveFile(file, new File(new File(cdrFileDoneDir), file.getName()));
		}
	}

	/**
	 * 话单下载路径辅助方法
	 *
	 * @param path
	 * @return
	 */
	public String analysiImsPath(String path, String date) {
		String[] strings = path.split("/");
		StringBuilder sBuilder = new StringBuilder();
		for (int i = 1; i < strings.length; i++) {
			if (i == strings.length - 1) {
				sBuilder.append("/").append(date+ "-").append(strings[i]);
			} else {
				sBuilder.append("/").append(strings[i]);
			}
		}
		return sBuilder.toString();
	}

	/**
	 * 话单下载路径辅助方法
	 *
	 * @param path
	 * @return
	 */
	public String analysiVgcPath(String path, String date) {
		String[] strings = path.split("/");
		StringBuilder sBuilder = new StringBuilder();
		for (int i = 1; i < strings.length; i++) {
			if (i == strings.length - 1) {
				sBuilder.append("/").append(date.replaceAll("-","")+ "-").append(strings[i]);
			} else {
				sBuilder.append("/").append(strings[i]);
			}
		}
		return sBuilder.toString();
	}

	private String analysisVgcStorePath(String subDirs, String path){
		String storePath="";
		if(path.contains("CDF")){
			storePath=subDirs +File.separator+"CDF"+ File.separator + this.ftpConf.getNetElementID() + File.separator;
		}else if(path.contains("OFFLINE")){
			storePath=subDirs +File.separator+"OFFLINE"+ File.separator + this.ftpConf.getNetElementID() + File.separator;
		}else if(path.contains("ONLINE")){
			storePath=subDirs +File.separator+"ONLINE"+ File.separator + this.ftpConf.getNetElementID() + File.separator;
		}else if(path.contains("ZERO")){
			storePath=subDirs +File.separator+"ZERO"+ File.separator + this.ftpConf.getNetElementID() + File.separator;
		}else if(path.contains("BGwOutput")){
			storePath=subDirs +File.separator+"CHF"+ File.separator + this.ftpConf.getNetElementID() + File.separator;
		}
		return storePath;
	}

	public FTPClient getFtpClient() {
		return ftpClient;
	}

	public void setFtpClient(FTPClient ftpClient) {
		this.ftpClient = ftpClient;
	}

    public void download_ORGINALIMSCDR(String subDirs, String date) {
		try {
			String path = this.ftpConf.getPath();

			log.info(path + " date " + date + " analysiPath(path, date) " + analysiImsPath(path, date));
			boolean changFlag = ftpClient.changeWorkingDirectory(analysiImsPath(path, date));
			int fileCount = 0;
			if (changFlag) {
				ftpClient.enterLocalPassiveMode();
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
				FTPFile[] ftpFiles = ftpClient.listFiles();
				log.info("===== ftpFiles num: " + ftpFiles.length + " date :" + date + " analysiPath(path, date): "
						+ analysiImsPath(path, date));
				List<FTPFile> ll = new ArrayList<FTPFile>();
				for (int m = 0; m < ftpFiles.length; m++) {
					ll.add(ftpFiles[m]);
				}
				for (int i = 0; i < ll.size(); i++) {
					FTPFile ftpFile = ll.get(i);
					if (!ftpFile.getName().equals(".") && !ftpFile.getName().equals("..") && !ftpFile.isDirectory()) {
							fileCount++;
							String originalName=new String(ftpFile.getName().getBytes("ISO-8859-1"), "UTF-8");
							File storeDir = FileUtil.newDirs(
									subDirs + File.separator + this.ftpConf.getHost().replaceAll("\\.","_") + File.separator+date);
							File localFile = new File(storeDir, originalName);
							if (!localFile.exists()) {
								OutputStream outputStream = new FileOutputStream(localFile);
								int remark=0;
								try {
									System.out.println(ftpFile.getName());
									retrieveFile(ftpFile.getName(), outputStream, remark);
								}catch (Exception ex){
									log.error(ftpFile.getName());
								}
								outputStream.close();
								if(!ftpFile.getName().contains(".gz:")){
									gzipOriginalFile(localFile);
								}
							}
					}
				}
			} else {
				log.info("FtpCarrierUtil>> changeWorkingDirectory failed " + analysiImsPath(path, date) + " is not found");
			}
			log.info("==cg_cdrpath " + path + "====file download count is[ :" + fileCount + "]  path: "
					+ analysiImsPath(path, date));
		} catch (Exception e) {
			log.info("FtpCarrierUtil>>file download exception：" + e.getMessage(), e);
		}
	}

	private void retrieveFile(String fileName,OutputStream outputStream,int remark) throws Exception {
		try {
			ftpClient.retrieveFile(fileName, outputStream);
		} catch (IOException e) {
			log.error("retrieveFile"+fileName+":"+e.getMessage());
			try {
				Thread.sleep(4000);
				this.connect();
			} catch (Exception exception) {
				log.error("retrieveFile connect"+fileName+":"+exception.getMessage());
			}
			retrieveFile(fileName,outputStream,remark);
		}finally {
			remark=remark+1;
		}
		if(remark==25){
			throw new Exception("fileName 下载失败"+fileName);
		}
	}

	private void gzipOriginalFile(File localFile) {
		Process procMv;
		String[] cmdMv = new String[3];
		cmdMv[0] = "sh";
		cmdMv[1] = "-c";
		cmdMv[2] = "/usr/bin/gzip "
				+localFile.getPath();
		try {
			procMv = Runtime.getRuntime().exec(cmdMv);
			BufferedReader brMv = new BufferedReader(new InputStreamReader(procMv.getInputStream()));
			String lineMv;
			while ((lineMv = brMv.readLine()) != null) {
				if (lineMv.trim().endsWith("#")) {
					break;
				}
			}
			brMv.close();
			procMv.waitFor();
			procMv.destroy();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
